#ifndef NSYNTAXHIGNLIGHT_H
#define NSYNTAXHIGNLIGHT_H
#include <QtWidgets>
#include <QMutexLocker>
#include "tools/Gadget.h"
#include "tools/Diary.h"

class NSyntaxHignLight : public QSyntaxHighlighter{

    Q_OBJECT

public:

    NSyntaxHignLight(QTextDocument *docuMent=nullptr):QSyntaxHighlighter(docuMent){
        RdoMap_Switch.insert("CaseSensitive", false);
        RdoMap_Switch.insert("HighLightMutex", true);
        RdoMap_Integer.insert("overloadStdNum", 1000);
        infoOverLoadTimer.setInterval(500);
        NSyntaxHignLight::setCaseSensitive(false);
        connect(&infoOverLoadTimer, &QTimer::timeout, this, &NSyntaxHignLight::Timer);
    }

    //#添加数据
    void appendHignLight(QString expr, QColor backColor, QColor foreColor){
        RdoMap_Color["HighLight_Format"].insert(expr, qMakePair(backColor, foreColor));
        diary(QString("bkcolor r:%1 g:%2 b:%3 frcolor r:%4 g:%5 b:%6").arg(QString::number(backColor.red()),
                                                                           QString::number(backColor.green()),
                                                                           QString::number(backColor.blue()),
                                                                           QString::number(foreColor.red()),
                                                                           QString::number(foreColor.green()),
                                                                           QString::number(foreColor.blue())),
                                                                           Diary::Debug);
    }

    //#添加数据
    void appendHignLight(QString expr, Qt::GlobalColor backColor, Qt::GlobalColor foreColor){
        RdoMap_Color["HighLight_Format"].insert(expr, qMakePair(backColor, foreColor));
        QColor backColorE(backColor);
        QColor foreColorE(foreColor);
        diary(QString("bkcolor r:%1 g:%2 b:%3 frcolor r:%4 g:%5 b:%6").arg(QString::number(backColorE.red()),
                                                                           QString::number(backColorE.green()),
                                                                           QString::number(backColorE.blue()),
                                                                           QString::number(foreColorE.red()),
                                                                           QString::number(foreColorE.green()),
                                                                           QString::number(foreColorE.blue())),
                                                                           Diary::Debug);
    }


    void setTask(QMap<QString, QList<QString>> task){
        RdoMap_Task.swap(task);
    }

    void delTask(QString key){
        RdoMap_Task.remove(key);
    }

    //# 删除高亮数据，参数为 key
    void removeHighLightKey(QString keyExpr){
        RdoMap_Color["HighLight_Format"].remove(keyExpr);
    }

    //# 清空关键字数据
    void clearSpecialFormat(){
        RdoMap_Format["SpecialFormat"].clearBackground();
        RdoMap_Format["SpecialFormat"].clearForeground();
    }

    //# 将正则字符串转小写
    QString skipTolowerFromExpr(QString extractStr){
        QString regExprStr;
        QRegularExpression regExpr("\\\\[a-zA-Z]");
        QList<QString> matchSpecialList = definfc.getGlobalMatching(extractStr, regExpr);
        QList<QString> splitchar = extractStr.toLower().split(regExpr);
        if (!splitchar.isEmpty() && !matchSpecialList.isEmpty())
        {
            for(int sec = 0; sec < splitchar.count(); sec++)
            {
                if (sec > 0)
                {
                    if (sec == matchSpecialList.count())
                    {
                        regExprStr.append(splitchar[sec]);
                    }
                    else
                    {
                        regExprStr.append(splitchar[sec] + matchSpecialList[sec]);
                    }
                }
                else
                {
                    regExprStr.append(splitchar[sec] + matchSpecialList[sec]);
                }
            }
        } else
        {
            regExprStr.append(extractStr.toLower());
        }
        return regExprStr;
    }

    //# 大小写敏感设置
    void setCaseSensitive(bool Enable){
        RdoMap_Switch["CaseSensitive"] = Enable;
    }

    void setSpecialEcho(bool echo){
        RdoMap_Switch["SpecialEcho"] = echo;
    }

    void ThreadBlockLoad(QPair<QString, int> i){
        QString regexp = i.first;
        int capStart = i.second;
        QTextCursor cursor = document()->find(regexp, capStart);
        rehighlightBlock(cursor.block());
    }


    void Timer(){
        RdoMap_Switch["HighLightMutex"] = false; //# 打开开关
        RdoMap_Integer["overloadCount"] = 0;  //# 将累计值重置，以屏蔽高数据量的高亮设置避免卡顿
    }

    //# 按焦点位置设置高亮，Text 是块字符，非全局字符
    void highlightBlock(const QString &Text){
        RdoMap_Integer["overloadCount"] += 1;
         //# 定时器未关闭，则打开
        if (RdoMap_Integer["overloadCount"] < RdoMap_Integer["overloadStdNum"])
        {
            RdoMap_Switch["HighLightMutex"] = false;
        }

        else
        {
            RdoMap_Switch["HighLightMutex"] = true; //# 打开开关
            if (!infoOverLoadTimer.isActive()) infoOverLoadTimer.start();
        }

        if (!RdoMap_Switch["HighLightMutex"]) //#开关为打开状态时，设置高亮
        {
            QTextCharFormat hignLightFormat;
            QMap<QString, QPair<QColor, QColor>> HignData = RdoMap_Color["HighLight_Format"];
            QTextCharFormat specialFormat = RdoMap_Format["SpecialFormat"];
            for(int N = 0; N < HignData.count(); N++)
            {
                QString findTextExpr = HignData.keys()[N];
                QColor backColor = HignData.values()[N].first;
                QColor foreColor = HignData.values()[N].second;
                hignLightFormat.setBackground(backColor);
                hignLightFormat.setForeground(foreColor);
                QRegularExpressionMatchIterator i;
                if (RdoMap_Switch["CaseSensitive"])
                {
                    QRegularExpression reg(findTextExpr);
                    i = reg.globalMatch(Text);
                }
                else
                {
                    QRegularExpression reg(skipTolowerFromExpr(findTextExpr));
                    i = reg.globalMatch(Text.toLower());
                }
                while (i.hasNext())
                {
                    QRegularExpressionMatch match = i.next();
                    if (RdoMap_Switch["SpecialEcho"])
                    {
                        if (specialFormat.isEmpty())
                        {
                            setFormat(match.capturedStart(), match.capturedLength(), hignLightFormat);
                        }
                        else
                        {
                            setFormat(match.capturedStart(), match.capturedLength(), specialFormat);
                        }
                    }
                    else
                    {
                            setFormat(match.capturedStart(), match.capturedLength(), hignLightFormat);
                    }
                }
            }
        }

        QStringList keys = RdoMap_Task.keys();
        foreach(QString key, keys)
        {
            if (key == TIMER_TASK.SERIALFUNC_REBOOTIMER)
            {
                foreach(QString expr, RdoMap_Task[key])
                {
                    QRegularExpression reg(expr);
                    if (!reg.match(Text).capturedTexts().join("").isEmpty())
                    {
                        emit taskMatchtrue(key);
                    }
                }
            }
        }
    }

protected:
    //# 函数为凸显关键字预留，因此直接赋值，不累加
    virtual void setSpecialFormat(QTextCharFormat format){
        RdoMap_Format["SpecialFormat"] = format;
    }

    Extend definfc;

private:
    QMap<QString, QMap<QString, QPair<QColor, QColor>>> RdoMap_Color;
    QMap<QString, QTextCharFormat> RdoMap_Format;
    QMap<QString, bool> RdoMap_Switch;
    QMap<QString, int> RdoMap_Integer;
    QMap<QString, QList<QString>> RdoMap_Task;
    QTimer infoOverLoadTimer;

signals:
    void taskMatchtrue(QString);

};
#endif



